﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using Pavilion.DesignerTool.ViewTools.ConnectableListBox;

namespace Pavilion.DesignerTool
{
    public class AnimationResourceData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public string ResourceName { get { return AnimationResource.Name; } set { SetResourceName(value); } }
        public ObservableCollection<AnimationLayer> AnimationLayerCollection { get; private set; }
        public NotifiableCollection<AnimationData> AnimationDataCollection { get { return AnimationDataDictionary.ValueCollection; } }
        public ContainerNodeWrapper RootContainerNodeWrapper { get; private set; }
        public AnimationLayer CurrentAnimationLayer { get { return _currentAnimationLayer; } set { _currentAnimationLayer = value; OnPropertyChanged("CurrentAnimationLayer"); } }

        private AnimationResource AnimationResource { get; set; }
        private NotifiableDictionary<Animation, AnimationData> AnimationDataDictionary { get; set; }
        private AnimationXmlSerializer AnimationSerializer { get; set; }
        private ScriptXmlSerializer ScriptXmlSerializer { get; set; }

        private AnimationLayer _currentAnimationLayer;

        public AnimationResourceData(string resourceName)
        {
            this.AnimationResource = ResourceManager.Instance[resourceName] as AnimationResource;

            AnimationLayerCollection = new ObservableCollection<AnimationLayer>();
            AnimationDataDictionary = new NotifiableDictionary<Animation, AnimationData>();
            AnimationSerializer = new AnimationXmlSerializer();
            ScriptXmlSerializer = new ScriptXmlSerializer();

            foreach (Animation animation in AnimationResource.AnimationList)
                AnimationDataDictionary.Add(animation, new AnimationData(animation));

            AnimationResource.AnimationAdded += (Animation animation) => { AnimationDataDictionary.Add(animation, new AnimationData(animation)); };
            AnimationResource.AnimationRemoved += (Animation animation) => { AnimationDataDictionary.Remove(animation); };

            RootContainerNodeWrapper = new ContainerNodeWrapper(AnimationResource.RootContainer, this);

            CreateAnimationLayer();
        }

        public void Save()
        {
            foreach (AnimationData animationSaveData in AnimationDataDictionary.ValueCollection)
                animationSaveData.Save(AnimationResource.RawDataPath, AnimationResource.ResourcePath);

            XDocument animationListDocument = AnimationSerializer.SerializeCollection(AnimationResource.AnimationList);
            animationListDocument.Save(AnimationResource.ResourcePath + "AnimationList.xml");

            XDocument nodeScriptDocument = ScriptXmlSerializer.SerializeScript(AnimationResource.RootContainer);
            nodeScriptDocument.Save(AnimationResource.ResourcePath + "Script.xml");
        }

        public void CreateAnimationLayer()
        {
            AnimationLayer animationLayer = new AnimationLayer(AnimationDataDictionary.ValueCollection);

            AnimationLayerCollection.Add(animationLayer);

            CurrentAnimationLayer = animationLayer;
        }

        public Animation AddNewAnimation()
        {
            return AnimationResource.AddNewAnimation();
        }

        public AnimationData GetAnimationData(Animation animation)
        {
            if (animation == null)
                return null;

            return AnimationDataDictionary[animation];
        }

        private void SetResourceName(string value)
        {
            if (AnimationResource.Name == value)
                return;

            string originalDirectory = AnimationResource.ResourcePath;
            AnimationResource.Name = value;

            if (Directory.Exists(originalDirectory))
                Directory.Move(originalDirectory, AnimationResource.ResourcePath);

            OnPropertyChanged("ResourceName");
        }

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
